import React, {PropsWithChildren, useCallback, useMemo, useState} from 'react'
import {View} from "@tarojs/components";
import styles from "./scratchDocumentDetail.module.sass"
import scratchDocumentStore, {
    ScratchDocumentData,
    ScratchDocumentItem,
    ScratchDocumentStorageKeyPrefix
} from "../store/ScratchDocumentStore";
import {Button, Cell, CellGroup, Checkbox, SafeArea, Space} from "@nutui/nutui-react-taro";
import {OffsetDateTime} from "@js-joda/core";
import {DATE_WITH_HOUR_MINUTE_FORMATER} from "../utils/Date";
import {Add, Top} from "@nutui/icons-react-taro";
import ExportToExcelConfigurationDialog from "../components/ExportToExcelConfigurationDialog";
import {ExcelColumn, exportToWorkbook, saveAndOpenWorkbook} from "../utils/ExcelUtils";
import Taro, {useLoad} from "@tarojs/taro";
import ArrayUtils from "@zxy-cn/array-utils";
import ScanBarcodeButton from "../components/ScanBarcodeButton";
import {barcodeRepeated, scanSuccess} from "../utils/ScanCodeUtils";
import SelectGoodsPopup from "../components/SelectGoodsPopup";
import ScratchDocumentItemCell from "../components/ScratchDocumentItemCell";
import {getGoodsDetail, getGoodsDetailByBarcode} from "../apis/GoodsApi";
import {observer} from "mobx-react";
import MyNavigationBar from "../components/MyNavigationBar";

export interface ScratchDocumentDetailProps extends PropsWithChildren {

}


const SCRATCH_DOCUMENT_ITEMS_EXPORT_COLUMNS_STORAGE_KEY = "SCRATCH_DOCUMENT_ITEMS_EXPORT_COLUMNS"

const ScratchDocumentDetail: React.FC<ScratchDocumentDetailProps> = ({}) => {
    const [createdDateTime, setCreatedDateTime] = useState<string>()
    const [useAmount, setUseAmount] = useState(false)
    const [useNote, setUseNote] = useState(false)
    useLoad(param => {
        setUseAmount(Boolean(param.useAmount))
        setUseNote(Boolean(param.useNote))
        setCreatedDateTime(param.createdDateTime)
    })
    const data = useMemo(() => {
        if (createdDateTime) {
            return scratchDocumentStore.documents.find(it => it.createdDateTime === createdDateTime)
        } else {
            return undefined
        }
    }, [createdDateTime, scratchDocumentStore.documents])

    const columns = useMemo(() => {
        const columns: ExcelColumn<ScratchDocumentItem>[] = [{
            key: "barcode",
            header: "条码",
            renderToString: item => {
                if (item.subGoods) {
                    return item.barcode + `|${item.subGoods.number}）`
                } else {
                    return item.barcode
                }
            }
        }, {
            key: "name",
            header: "名称",
            renderToString: item => {
                if (item.subGoods) {
                    return item.subGoods.name + `（${item.name}）`
                } else {
                    return item.name
                }
            }
        }, {
            key: "price",
            header: "价格",
        }];
        if (useAmount) {
            columns.push({
                    key: "amount",
                    header: "数量",
                    renderToString: item => {
                        return `${item.amount}${item.unit?.name ?? ""}`
                    }
                },
            )
        }
        if (useNote) {
            columns.push({key: "note", header: "备注",})
        }
        return columns
    }, [useAmount, useNote])
    const [exportToExcelDialogVisible, setExportToExcelDialogVisible] = useState(false)
    const [selectGoodsPopupVisible, setSelectGoodsPopupVisible] = useState(false)

    function scrollToBottom() {
        const query = Taro.createSelectorQuery()
        query.selectViewport().boundingClientRect((rect: any) => {
            Taro.pageScrollTo({
                scrollTop: rect.height,
            })
        }).exec()
    }

    let onScanSuccess = useCallback(async (barcode: string, continueScan, data: ScratchDocumentData) => {
            let result = await Taro.getStorage({key: ScratchDocumentStorageKeyPrefix + data.createdDateTime});
            const persist = result.data as ScratchDocumentData
            if (persist.items.map(it => it.barcode).includes(barcode)) {
                await barcodeRepeated(`草稿单中已存在此货品\t${barcode}`)

                setTimeout(() => {
                    continueScan()
                }, 100)
                return
            }
            const detail = await getGoodsDetailByBarcode(barcode)

            let item = detail.data
            let array = Array.from(persist.items)
            array.push({...item, id: item.id})

            await scratchDocumentStore.set({...persist, items: array})
            await scanSuccess()
            scrollToBottom()
            setTimeout(() => {
                continueScan()
            }, 100)
        },
        [scratchDocumentStore.documents])
    return <>
        <MyNavigationBar>草稿单详情</MyNavigationBar>
        {data && <>
            <CellGroup divider={false} style={{position: "sticky", top: 0, zIndex: 999}}>
                <Cell>创建于{OffsetDateTime.parse(data.createdDateTime).format(DATE_WITH_HOUR_MINUTE_FORMATER)}</Cell>
                <Cell>
                    <Space>
                        <Checkbox label={"数量"} checked={data.useAmount} onChange={(value) => {
                            scratchDocumentStore.set({
                                ...data,
                                useAmount: value,
                            })
                        }}/>
                        <Checkbox label={"备注"} checked={data.useNote} onChange={value => {
                            scratchDocumentStore.set({
                                ...data,
                                useNote: value,
                            })
                        }}/>
                    </Space>
                </Cell>
                {<Cell extra={
                    <Space>
                        <Button onClick={async () => {
                            setExportToExcelDialogVisible(true)
                        }}>导出</Button>
                        <ExportToExcelConfigurationDialog
                            visible={exportToExcelDialogVisible}
                            rememberedColumnsStorageKey={SCRATCH_DOCUMENT_ITEMS_EXPORT_COLUMNS_STORAGE_KEY}
                            selectableColumns={columns}
                            onCancel={() => {
                                setExportToExcelDialogVisible(false)
                            }}
                            onConfirm={async values => {
                                let workbook = exportToWorkbook(data.items, columns.filter(it => values.includes(it.key)));
                                await saveAndOpenWorkbook(workbook, `草稿单${OffsetDateTime.parse(data.createdDateTime).format(DATE_WITH_HOUR_MINUTE_FORMATER)}`)
                                setExportToExcelDialogVisible(false)
                            }}/>
                        {<Button type={"danger"} fill={"outline"} onClick={async () => {
                            await scratchDocumentStore.delete(data.createdDateTime)
                        }}>删除</Button>}
                    </Space>
                }/>}
            </CellGroup>
            {data.items.map((item, index) => {
                return <ScratchDocumentItemCell data={item}
                                                key={item.subGoods?item.id + "-"+item.subGoods.id:item.id}
                                                onDelete={async () => {
                                                    ArrayUtils.remove(data!.items, item)
                                                    await scratchDocumentStore.set({
                                                        ...data,
                                                        items: Array.from(data?.items),
                                                    })
                                                }}
                                                onUpdateAmount={async (value, unitId) => {
                                                    let items = Array.from(data!.items);
                                                    items[index] = {
                                                        ...items[index],
                                                        amount:value,
                                                        unit:items[index].units.find(it => it.id === unitId)
                                                    }
                                                    await scratchDocumentStore.set({
                                                        ...data,
                                                        items: items
                                                    })
                                                }}
                                                onUpdateNote={async (note) => {

                                                    let items = Array.from(data!.items);
                                                    items[index].note = note
                                                    await scratchDocumentStore.set({
                                                        ...data,
                                                        items: items
                                                    })
                                                }}
                                                showAmount={data.useAmount}
                                                showNote={data.useNote}
                />
            })}
            {!!data && <View style={{height: 48, width: "100%"}}/>}
            {!!data && <View className={styles.bottomBar}>
                <Space className={styles.bottomSpace}>
                    <Button fill={"outline"} icon={<Top/>} onClick={() => {
                        Taro.pageScrollTo({
                            scrollTop: 0,
                            duration: 300,
                        })
                    }}>回到顶部</Button>
                    {<Button icon={<Add/>} type={"primary"} onClick={() => {
                        setSelectGoodsPopupVisible(true)
                    }}>添加{`(${data.items.length})`}</Button>}
                    {<ScanBarcodeButton
                        onScanSuccess={(barcode, continueScan) => onScanSuccess(barcode, continueScan, data)}>扫码</ScanBarcodeButton>}
                </Space>
                <SafeArea position={"bottom"}/>
            </View>}
        </>}
        <SelectGoodsPopup visible={selectGoodsPopupVisible} onClose={() => setSelectGoodsPopupVisible(false)}
                          excludeGoodsIds={data?.items.map(it => it.id) ?? []}
                          existedGoodsList={data?.items?.flatMap(it => ({
                              name:it.name,
                              barcode:it.barcode,
                              id:it.id,
                              goodsId: it.id,
                              subGoods: it.subGoods?{
                                  amount:0,
                                  ...it.subGoods,
                              }:undefined
                          })) ?? []}
                          onConfirm={async value => {
                              Promise.all(value.map(it => {
                                  return new Promise<ScratchDocumentItem>((resolve, reject) => {
                                      getGoodsDetail(it.goodsId).then(response => {
                                          const item = response.data
                                          resolve({
                                              id: item.id,
                                              name: item.name,
                                              subGoods: item.subGoodsList.find(subGoods => subGoods.id === it.subGoodsId),
                                              amount: data?.useAmount ? 1 : 0,
                                              units: item.units,
                                              unit: undefined,
                                              note: undefined,
                                              barcode: item.barcode,
                                              price: item.price,
                                          } as ScratchDocumentItem)
                                      }).catch(reject)
                                  })
                              })).then(async array => {
                                  await scratchDocumentStore.set({
                                      ...data!,
                                      items: data!.items.concat(array)
                                  })
                                  scrollToBottom()
                              })


                          }}/>
    </>
}

export default observer(ScratchDocumentDetail)


